#include "Delay.h"
#include "LCD1602.h"
#include "matrixKey.h"
#include <REGX52.H>
#include <stdlib.h>
#include <string.h>
#define bool bit bdata
#define MAXPAGENUM 5 // 拉到内存池最大处往会两页会爆

/*鏈表單元*/

typedef struct page {
  struct page *last;
  char string[17];
  struct page *next;
} page;

/*申請新鏈表節點*/
page *newpage(page *lastpage);

int main(void) {
  char xdata pool
      [MAXPAGENUM *
       sizeof(
           page)]; // 用於動態分配内存空間的池，MAXPAGENUM個page類型的大小，設置在擴展RAM
  char T9choose;
  char lastkey = 0; // 上次的按键
  char key;         // 按键值
  char pagenum = 1; // 总页数
  char pagetotal = 1;
  page *pages;
  //  char tmp;                             // 临时变量
  char cur = 0;    // 第一行屏幕的cur
  char vircur = 0; // 第一行全文的cur
  bool isnum = 0;  // 是否数字输入
  bool iscap = 0;  // 是否大写
  bool isinT9 = 0; // 是否在候选词状态
  // char string[17] = "                "; // 16个空格,第一行缓冲区
  char *T9; // T9候选字符串头
  init_mempool(pool, sizeof(pool));
  pages = newpage(NULL); // 頭節點 aka 鏈表初始化

start:
  while (1) { // 程序开始
    if (isinT9) {
      pages->string[cur] = T9[T9choose];
    } else
      T9 = "    ";
    init();
    printf(pages->string); // 显示第一行
    setcur(0x40);
    printf("%s   %c%c%c %c %d/%d", T9, ' ' + (char)46 * isnum,
           ' ' + (char)53 * isnum, ' ' + (char)45 * isnum,
           'a' - (char)iscap * 32, pagenum,
           pagetotal); // 显示第二行：候选字母 数字模式指示
                       // 大小写指示 当前页/总页
    lastkey = key;
    setcur(0x00 + cur);
  keyboard:
    key = getkey(); // 显示的时间窗口
  switchbegin:
    switch (key) {
    case 1: // T9_1
      if (isnum) {
        pages->string[cur] = '1';
        ++vircur;
        break;
      }
      if (lastkey == 1) {
        if (T9choose < 3)
          ++T9choose;
        else
          T9choose = 0;
        break;
      }
      T9 = ",.?!";
      isinT9 = 1;
      break;
    case 2: // T9_2
      if (isnum) {
        pages->string[cur] = '2';
        ++vircur;
        break;
      }
      if (iscap)
        T9 = "ABC ";
      else
        T9 = "abc ";
      isinT9 = 1;
      if (lastkey == 2) {
        if (T9choose < 2)
          ++T9choose;
        else
          T9choose = 0;
      }
      break;
    case 3: // T9_3
      if (isnum) {
        pages->string[cur] = '3';
        ++vircur;
        break;
      }
      if (iscap)
        T9 = "DEF ";
      else
        T9 = "def ";
      isinT9 = 1;
      if (lastkey == 3) {
        if (T9choose < 2)
          ++T9choose;
        else
          T9choose = 0;
      }
      break;
    case 4: // TODO
      if (isnum) {
        pages->string[cur] = '0';
        ++vircur;
        break;
      }
      break;
    case 5: // T9_4
      if (isnum) {
        pages->string[cur] = '4';
        ++vircur;
        break;
      }
      if (iscap)
        T9 = "GHI ";
      else
        T9 = "ghi ";
      isinT9 = 1;
      if (lastkey == 5) {
        if (T9choose < 2)
          ++T9choose;
        else
          T9choose = 0;
      }
      break;
    case 6: // T9_5
      if (isnum) {
        pages->string[cur] = '5';
        ++vircur;
        break;
      }
      if (iscap)
        T9 = "JKL ";
      else
        T9 = "jkl ";
      isinT9 = 1;
      if (lastkey == 6) {
        if (T9choose < 2)
          ++T9choose;
        else
          T9choose = 0;
      }
      break;
    case 7: // T9_6
      if (isnum) {
        pages->string[cur] = '6';
        ++vircur;
        break;
      }
      if (iscap)
        T9 = "MNO ";
      else
        T9 = "mno ";
      isinT9 = 1;
      if (lastkey == 7) {
        if (T9choose < 2)
          ++T9choose;
        else
          T9choose = 0;
      }
      break;
    case 8: // capslock
      iscap = !iscap;
      if (isinT9) {
        --T9choose;
        key = lastkey;
        goto switchbegin; // 弄不掉的goto
      } else
        break;
    case 9: // T9_7
      if (isnum) {
        pages->string[cur] = '7';
        ++vircur;
        break;
      }
      if (iscap)
        T9 = "PQRS";
      else
        T9 = "pqrs";
      isinT9 = 1;
      if (lastkey == 9) {
        if (T9choose < 3)
          ++T9choose;
        else
          T9choose = 0;
      }
      break;
    case 10: // T9_8
      if (isnum) {
        pages->string[cur] = '8';
        ++vircur;
        break;
      }
      if (iscap)
        T9 = "TUV ";
      else
        T9 = "tuv ";
      isinT9 = 1;
      if (lastkey == 10) {
        if (T9choose < 2)
          ++T9choose;
        else
          T9choose = 0;
      }
      break;
    case 11: // T9_9
      if (isnum) {
        pages->string[cur] = '9';
        ++vircur;
        break;
      }
      if (iscap)
        T9 = "WXYZ";
      else
        T9 = "wxyz";
      isinT9 = 1;
      if (lastkey == 11) {
        if (T9choose < 3)
          ++T9choose;
        else
          T9choose = 0;
      }
      break;
    case 12: // NUM
      isnum = !isnum;
      if (isinT9) {
        isinT9 = 0;
        pages->string[cur] = ' ';
      }
      break;
    case 13: //<-
      if (isinT9) {
        key = lastkey;
        break;
      }
      --vircur;
      break;
    case 14: //->
      if (isinT9) {
        key = lastkey;
        break;
      }
      ++vircur;
      break;
    case 15: // ×
      if (isinT9)
        isinT9 = 0;
      pages->string[cur] = ' ';
      break;
    case 16: // ●
      if (isinT9) {
        ++vircur;
        isinT9 = 0;
      }
      break;
    }
    if (lastkey != key)
      T9choose = 0;
    if (vircur < 0) {
      vircur = 0;
      goto keyboard;
    }
    if (vircur > (MAXPAGENUM * 16 - 1)) {
      vircur = MAXPAGENUM * 16 - 1;
      goto start;
    }
    if ((vircur / 16 + 1) < pagenum)
      pages = pages->last;
    if ((vircur / 16 + 1) > pagenum && (vircur / 16 + 1) <= pagetotal)
      pages = pages->next;
    pagenum = vircur / 16 + 1;
    if (pagenum > pagetotal) {
      pagetotal = pagenum;
      pages->next = newpage(pages);
      pages = pages->next;
    }
    cur = vircur % 16;
  }
}
page *newpage(page *lastpage) {
  page *this = (page *)malloc(sizeof(page));
  (*this).last = lastpage; // same as this->last
  strcpy(this->string, "                ");
  this->next = NULL;
  return this;
}

/*链表增长
 * page->next = newpage(pages);
 * pages = pages -> next；
 */
